package at.fhooe.mc.duel_game.activities;

import java.util.ArrayList;
import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import at.fhooe.mc.duel_game.DeviceArrayAdapter;
import at.fhooe.mc.duel_game.DeviceItem;
import at.fhooe.mc.duel_game.DiscoverState;
import at.fhooe.mc.duel_game.GuiHelpers;
import at.fhooe.mc.duel_game.R;

public class GetDevicesActivity extends Activity implements OnClickListener {

	private BluetoothAdapter mBtAdapter;
	private DeviceArrayAdapter mdDevicesArrayAdapter;

	private ArrayList<DeviceItem> mDeviceList = new ArrayList<DeviceItem>();

	// debug flag
	private static final boolean D = true;
	private static final String TAG = "Bluetooth Discovery";

	// Intent for device selection
	public static String EXTRA_DEVICE_ADDRESS = "device_address";

	// Intent request codes
	static final int REQUEST_CONNECT_DEVICE = 1;
	static final int REQUEST_ENABLE_BT = 3;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

		requestWindowFeature(Window.FEATURE_NO_TITLE);

		setContentView(R.layout.layout_get_devices);

		getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
						| WindowManager.LayoutParams.FLAG_FULLSCREEN);

		Button b = (Button) findViewById(R.id.buttonSearchNewDevices);
		b.setOnClickListener(this);

		// initialize array adapters
		mdDevicesArrayAdapter = new DeviceArrayAdapter(this,
				R.id.textViewListViewDeviceName, mDeviceList);

		ListView listView = (ListView) findViewById(R.id.listViewDevices);
		listView.setAdapter(mdDevicesArrayAdapter);
		listView.setOnItemClickListener(mDeviceListener);

		registerBroadcastsReceiver();
	}

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();

		if (initBluetooth()) {
			enableBluetooth();
		} else {
			finish();
		}
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();

		if (mNewDeviceReceiver != null)
			this.unregisterReceiver(mNewDeviceReceiver);
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();

		if (enableBluetooth()) {
			// start device discovery if bluetooth is enabled
			doDiscovery();
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);

		switch (requestCode) {
		case REQUEST_ENABLE_BT:
			if (resultCode == RESULT_OK) {
				setState(DiscoverState.BLUETOOTH_ENABLED);
			} else {
				setState(DiscoverState.BLUETOOTH_DISABLED);
			}
			break;
		}
	}

	private void registerBroadcastsReceiver() {
		// Register for broadcasts when a device is discovered
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		this.registerReceiver(mNewDeviceReceiver, filter);

		// Register for broadcasts when discovery has finished
		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		this.registerReceiver(mNewDeviceReceiver, filter);
	}

	private void setStatusText(String status) {
		TextView text = (TextView) findViewById(R.id.textViewStatusGetDevices);
		text.setText(status);
	}

	private void setStatusText(int stringId) {

		String value = "invalid id!";

		try {
			value = getResources().getString(stringId);
		} catch (Exception ex) {
			Log.e(TAG, ex.getMessage());
		}

		setStatusText(value);
	}

	private void setState(DiscoverState state) {
		View progressBar = findViewById(R.id.progressBarDiscovering);
		Button buttonSearch = (Button) findViewById(R.id.buttonSearchNewDevices);

		switch (state) {

		case BLUETOOTH_INIT:
			break;

		case BLUETOOTH_NOT_SUPPORTED:
			GuiHelpers.showAlertDialog(getApplicationContext(), "Bluetooth",
					getResources().getString(R.string.bluetoothNotSupported));
			break;

		case BLUETOOTH_DISABLED:
			setStatusText(R.string.bluetoothDisabled);
			break;

		case BLUETOOTH_ENABLED:
			setStatusText(R.string.bluetoothEnabled);

			// get paired devices
			getPairedDevices();

		case BLUETOOTH_DISCOVER:
			setStatusText(R.string.statusDiscovering);
			progressBar.setVisibility(View.VISIBLE);
			buttonSearch.setText(getResources().getString(
					R.string.buttonTextCancel));
			break;

		case BLUETOOTH_DISCOVER_FINISHED:
			setStatusText(R.string.statusDisvoverFinished);
			progressBar.setVisibility(View.INVISIBLE);
			buttonSearch.setText(getResources().getString(
					R.string.buttonTextSearch));
			break;
		}
	}

	private boolean initBluetooth() {
		// get the blueooth adapter of the device
		mBtAdapter = BluetoothAdapter.getDefaultAdapter();

		if (mBtAdapter == null) {
			// device doesn't support bluetooth
			setState(DiscoverState.BLUETOOTH_NOT_SUPPORTED);
			return false;
		}

		return true;
	}

	private boolean enableBluetooth() {
		if (mBtAdapter.isEnabled() == false) {
			// enable bluetooth
			Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(intent, REQUEST_ENABLE_BT);
			return false;
		} else {
			setState(DiscoverState.BLUETOOTH_ENABLED);
			return true;
		}
	}

	private int getIconId(BluetoothClass bluetoothClass) {
		switch (bluetoothClass.getMajorDeviceClass()) {
		case BluetoothClass.Device.Major.PHONE:
			return R.drawable.mobile;

		case BluetoothClass.Device.Major.COMPUTER:
			return R.drawable.laptop;

		default:
			return R.drawable.bluetooth;
		}
	}

	private boolean getPairedDevices() {
		Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

		mDeviceList.clear();

		// If there are paired devices
		if (pairedDevices.size() > 0) {
			// Loop through paired devices
			for (BluetoothDevice device : pairedDevices) {

				// Add the name and address to an array adapter to show in a
				// ListView
				if (device.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PHONE) {
					mDeviceList.add(new DeviceItem(device.getName(), device
							.getAddress(),
							getIconId(device.getBluetoothClass()), true));
				}
			}

			return true;
		}

		return false;
	}

	/**
	 * Start device discover
	 */
	private void doDiscovery() {
		if (D)
			Log.d(TAG, "doDiscovery()");

		// Indicate scanning in the title
		setState(DiscoverState.BLUETOOTH_DISCOVER);

		// If we're already discovering, stop it
		if (mBtAdapter.isDiscovering()) {
			mBtAdapter.cancelDiscovery();
		}

		// Request discover from BluetoothAdapter
		mBtAdapter.startDiscovery();
	}

	/**
	 * Cancel device discover
	 */
	private void cancelDiscovery() {
		if (D)
			Log.d(TAG, "cancelDiscovery()");

		// If we're already discovering, stop it
		if (mBtAdapter.isDiscovering()) {
			mBtAdapter.cancelDiscovery();
		}
	}

	private OnItemClickListener mDeviceListener = new OnItemClickListener() {
		public void onItemClick(android.widget.AdapterView<?> arg0,
				android.view.View arg1, int arg2, long arg3) {

			mBtAdapter.cancelDiscovery();

			DeviceItem item = null;

			item = mDeviceList.get(arg2);

			Intent intent = new Intent();
			intent.putExtra(EXTRA_DEVICE_ADDRESS, item.getMac());

			setResult(REQUEST_CONNECT_DEVICE, intent);
			finish();
		};
	};

	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.buttonSearchNewDevices:
			if (mBtAdapter.isDiscovering())
				cancelDiscovery();
			else
				doDiscovery();
			break;
		}
	}

	// The BroadcastReceiver that listens for discovered devices and
	// changes the title when discovery is finished
	private final BroadcastReceiver mNewDeviceReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();

			// When discovery finds a device
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				// Get the BluetoothDevice object from the Intent
				BluetoothDevice device = intent
						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				// If it's already paired, skip it, because it's been listed
				// already
				if (device.getBondState() != BluetoothDevice.BOND_BONDED
						&& device.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PHONE) {
					mdDevicesArrayAdapter.add(new DeviceItem(device.getName(),
							device.getAddress(), getIconId(device
									.getBluetoothClass()), false));
				}
				// When discovery is finished, change the Activity title
			} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
					.equals(action)) {
				setProgressBarIndeterminateVisibility(false);
				setState(DiscoverState.BLUETOOTH_DISCOVER_FINISHED);

			}
		}
	};

}
